#include <signal.h>
#include <iostream>
#include <unistd.h>
#include <sys/wait.h>
#include <cassert>
using namespace std;

void hander(int sig)
{
    cout<<"signal:"<<sig<<endl;
    sleep(1);
}

void PrintSig(sigset_t &sigpending)
{
    cout<<"pending bitmap"<<endl;//pending位图
    for(int signo=32;signo>0;signo--)
    {
        if(sigismember(&sigpending,signo)){
            cout<<"1";
        }
        else{
            cout<<"0";
        }
    }
    cout<<endl;
}
void handler(int signo)
{
    sigset_t pending;
    sigemptyset(&pending);
    cout<<"处理屏蔽信号"<<endl; 
    int n=sigpending(&pending);
    assert(n==0);
    cout<<"处理结束"<<endl;
    PrintSig(pending);
}
// int main()
// {
//     signal(SIGFPE,hander);//替换
//     int a=10/0;

//     return 0;
// }
 // 对2号信号进行自定义捕捉 --- 不让进程因为2号信号而终止
 int main(){
   // signal(2, handler);

    // 1. 屏蔽2号信号
    sigset_t block, oblock;
    sigemptyset(&block);
    sigemptyset(&oblock);
    sigaddset(&block, 2); // SIGINT --- 根本就没有设置进当前进程的PCB block位图中
    sigaddset(&block, 40); // SIGINT --- 根本就没有设置进当前进程的PCB block位图中

    // 0. for test: 如果我屏蔽了所有信号呢？？？
    // for(int signo = 1; signo <= 31; signo++) // 9， 19号信号无法被屏蔽， 18号信号会被做特殊处理
    //     sigaddset(&block, signo); // SIGINT --- 根本就没有设置进当前进程的PCB block位图中
    // 1.1 开始屏蔽2号信号，其实就是设置进入内核中
    int n = sigprocmask(SIG_SETMASK, &block, &oblock);
    assert(n == 0);
    // (void)n; // 骗过编译器，不要告警，因为我们后面用了n，不光光是定义
    std::cout << "block 2 signal success" << std::endl;
    std::cout << "pid: " << getpid() << std::endl;
    int cnt = 0;
    while (true)
    {
        // 2. 获取进程的pending位图
        sigset_t pending;
        sigemptyset(&pending);
        n = sigpending(&pending);
        assert(n == 0);
        // 3. 打印pending位图中的收到的信号
        PrintSig(pending);
        cnt++;

        // 4. 解除对2号信号的屏蔽
        if (cnt == 20)
        {
            std::cout << "解除对2号信号的屏蔽" << std::endl;
            n = sigprocmask(SIG_UNBLOCK, &block, &oblock); // 2号信号会被立即递达, 默认处理是终止进程
            assert(n == 0);
        }
        // 我还想看到pending 2号信号 1->0 : 递达二号信号！
        sleep(1);
    }
    return 0;
 }